<template>
  <div class="container">
    <el-card class="tree-card">
      <template #header>
        <div class="card-header">
          <el-icon>
            <Folder/>
          </el-icon>
          <span>菜单树</span>
        </div>
      </template>

      <div class="tree-search">
        <el-input
            v-model="treeFilterText"
            placeholder="菜单名称"
            clearable
            @input="filterTree"
        >
          <template #prefix>
            <el-icon>
              <Search/>
            </el-icon>
          </template>
        </el-input>
      </div>

      <div class="tree-container">
        <el-tree
            ref="treeRef"
            class="filter-list"
            :data="filteredTreeData"
            :props="treeProps"
            node-key="id"
            default-expand-all
            @node-click="handleNodeClick"
            :filter-node-method="filterNode"
        >
          <template #default="{ node, data }">
            <span class="tree-node">
              <el-icon v-if="node.isLeaf"><Document/></el-icon>
              <el-icon v-else><Folder/></el-icon>
              <span>{{ node.label }}</span>
            </span>
          </template>
        </el-tree>
      </div>
    </el-card>

    <el-card class="table-card">
      <template #header>
        <div class="card-header">
          <el-icon>
            <List/>
          </el-icon>
          <span>菜单列表</span>
          <span v-if="currentName" class="selection-hint">
            <span>当前菜单为:</span>
            <el-tag type="success" effect="plain" style="margin-right: 6px;">{{ currentName }}</el-tag>
            <DictSelect :model-value="currentType" dic-type-code="menu_type" displayOnly/>
          </span>
        </div>
      </template>

      <div class="query-form">
        <el-form :inline="true" :model="queryParams">
          <el-form-item label="菜单名称">
            <el-input
                v-model="search"
                placeholder="菜单名称"
                clearable
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleQuery">搜索</el-button>
            <el-button @click="resetQuery">重置</el-button>
          </el-form-item>
        </el-form>
      </div>

      <div class="table-toolbar">
        <el-button type="primary" @click="handleAdd" v-permission="['admin','insert_menu']"
                   :disabled="currentType =='B'">
          <el-icon>
            <Plus/>
          </el-icon>
          添加菜单
        </el-button>
        <el-button
            type="danger"
            :disabled="!selecteds.length"
            @click="handleBatchDelete"
            v-permission="['admin','delete_menu']"
        >
          <el-icon>
            <Delete/>
          </el-icon>
          删除菜单
        </el-button>
      </div>

      <!-- User Table -->
      <el-table
          :data="tableData"
          border
          style="width: 100%"
          @selection-change="handleSelectionChange"
          height="calc(100vh - 420px)"
          v-loading="loading"
      >
        <el-table-column type="selection" width="55"/>
        <el-table-column prop="menuId" label="ID" width="80"/>
        <el-table-column prop="menuCode" label="编码" width="120"/>
        <el-table-column prop="menuName" label="名称"/>
        <el-table-column prop="menuType" label="类型">
          <template #default="scope">
            <DictSelect :model-value="scope.row.menuType" dicTypeCode="menu_type" displayOnly></DictSelect>
          </template>
        </el-table-column>
        <el-table-column prop="menuUrl" label="路由地址 " width="240"/>
        <el-table-column prop="menuOrder" label="排序 " width="240"/>
        <el-table-column label="操作" width="150" fixed="right">
          <template #default="{ row }">
            <el-button v-permission="['admin','update_menu']" size="small" @click="handleEdit(row)">编辑</el-button>
            <el-button v-permission="['admin','delete_menu']" size="small" type="danger" @click="handleDelete(row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- Pagination -->
      <div class="pagination">
        <el-pagination
            v-model:current-page="queryParams.current"
            v-model:page-size="queryParams.size"
            :total="total"
            :page-sizes="[10, 20, 50]"
            layout="total, sizes, prev, pager, next"
            @size-change="handleQuery"
            @current-change="fetchTableData"
        />
      </div>
    </el-card>
    <EditDialog ref="EditRef" @submit="handleSubmit"></EditDialog>
  </div>
</template>

<script setup lang="ts">
import {ref, onMounted, watch, nextTick} from 'vue'
import {
  Folder,
  Document,
  Search,
  Plus,
  Delete,
  List
} from '@element-plus/icons-vue'
import {tableInfoApi} from '@/api/core';
import {PageQuery, TreeNode} from "@/types/api";
import {ElMessageBox, ElMessage} from 'element-plus'
import DictSelect from "@/components/DictSelect.vue";
import {MenuItem} from "@/views/menu/menu"
import EditDialog from "@/views/menu/edit.vue";

const EditRef = ref<InstanceType<typeof EditDialog>>()
const treeRef = ref()
const treeFilterText = ref('')
const filteredTreeData = ref<TreeNode<MenuItem>[]>([])

// menuId
const currentDepartment = ref('')
const currentName = ref('')
const currentType = ref('M')

// 记录上一次点击的节点 id
const lastClickedNode = ref<string | null>(null)
// 点击定时器
let clickTimer: NodeJS.Timeout | null = null

const search = ref('')

const queryParams = ref<PageQuery>({
  code: 'app_menu',
  current: 1,
  size: 10,
  queryParams: [{
    paramName: "menuName",
    relation: "like",
    paramValue: ""
  }, {
    paramName: "menuPreId",
    relation: "eq",
    paramValue: ""
  }],
  querySorts: [{
    paramName: "menuOrder",
    order: "desc"
  }]
})

const tableData = ref<MenuItem[]>([])
const total = ref(0)
const loading = ref(false)
const selecteds = ref<MenuItem[]>([])

// 属性映射
const treeProps = {
  children: 'children',
  label: 'label'
}

// 触发树筛选
const filterTree = () => {
  treeRef.value?.filter(treeFilterText.value)
}

// 树节点过滤逻辑
const filterNode = (value: string, data: TreeNode<MenuItem>) => {
  if (!value) return true
  return data.label.toLowerCase().includes(value.toLowerCase())
}

// 清空树节点选择
const clearTreeSelection = () => {
  treeRef.value?.setCurrentKey(null)
  currentDepartment.value = ''
  currentName.value = ''
  currentType.value = 'M'
}

// 树点击（支持双击取消，带 300ms 防抖）
const handleNodeClick = (data: TreeNode<MenuItem>) => {
  if (clickTimer) {
    clearTimeout(clickTimer)
    clickTimer = null
  }

  if (lastClickedNode.value === data.id) {
    // 双击同一个节点 → 取消选中
    clearTreeSelection()
    lastClickedNode.value = null
    nextTick(() => {
      handleQuery()
    })
  } else {
    // 延迟判定单击
    clickTimer = setTimeout(() => {
      currentDepartment.value = data.id
      currentName.value = data.label
      currentType.value = data.data?.menuType!
      lastClickedNode.value = data.id

      nextTick(() => {
        handleQuery()
      })
      clickTimer = null
    }, 300)
  }
}

// 搜索
const handleQuery = () => {
  queryParams.value.current = 1
  fetchTableData()
}

watch(search, (newVal) => {
  if (queryParams.value.queryParams && queryParams.value.queryParams[0]) {
    queryParams.value.queryParams[0].paramValue = newVal
  }
})

watch(currentDepartment, (newVal) => {
  if (queryParams.value.queryParams && queryParams.value.queryParams[1]) {
    queryParams.value.queryParams[1].paramValue = newVal
  }
})

// 查询
const fetchTableData = () => {
  loading.value = true
  if (queryParams.value.queryParams![1].paramValue == "") {
    queryParams.value.queryParams![1].relation = "isNull"
  }
  tableInfoApi.page(queryParams.value).then(res => {
    total.value = res.data.total
    tableData.value = res.data.records
  }).finally(() => {
    loading.value = false
    queryParams.value.queryParams![1].relation = "eq"
  })
}

// 重置
const resetQuery = () => {
  queryParams.value.size = 10
  search.value = ''
  clearTreeSelection()
  handleQuery()
}

// 多选
const handleSelectionChange = (val: MenuItem[]) => {
  selecteds.value = val
}

// 新增
const handleAdd = () => {
  if (currentDepartment.value == null) {
    EditRef.value?.openDialog(currentType.value)
  } else {
    EditRef.value?.openDialog(currentType.value, Number.parseInt(currentDepartment.value))
  }
}

// 编辑
const handleEdit = (row: MenuItem) => {
  EditRef.value?.openDialog(currentType.value, Number.parseInt(currentDepartment.value), row)
}

// 保存数据
const handleSubmit = (data: MenuItem) => {
  tableInfoApi.saveOrUpdate("app_menu", data).then(() => {
    ElMessage.success("保存菜单成功")
    queryMenuTree()
  })
}

// 删除单条
const handleDelete = (row: MenuItem) => {
  ElMessageBox.confirm(
      `是否确认删除菜单 "${row.menuCode}"？`,
      '删除确认',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
  ).then(() => {
    tableInfoApi.deleteById("app_menu", "" + row.menuId).then(() => {
      ElMessage.success("删除菜单成功")
      clearTreeSelection()
      queryMenuTree()
    })
  }).catch(() => {
    // 点击取消，不做操作
  })
}

// 批量删除
const handleBatchDelete = () => {
  if (!selecteds.value.length) return

  ElMessageBox.confirm(
      `是否确认删除选中的 ${selecteds.value.length} 个菜单？`,
      '批量删除确认',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
  ).then(() => {
    const ids = selecteds.value.map(item => item.menuId).join(',')
    tableInfoApi.deleteByIds("app_menu", ids).then(() => {
      ElMessage.success("批量删除菜单成功")
      selecteds.value = []
      clearTreeSelection()
      queryMenuTree()
    })
  }).catch(() => {
    // 点击取消，不做操作
  })
}

// 查询组织树
const queryMenuTree = () => {
  tableInfoApi.tree("app_menu").then((res) => {
    filteredTreeData.value = res.data
    handleQuery()
  })
}

onMounted(() => {
  queryMenuTree()
})
</script>



<style scoped>
.container {
  display: flex;
  gap: 16px;
  height: 100%;
}

.tree-card {
  width: 300px;
  flex-shrink: 0;
}

.table-card {
  flex: 1;
}

.card-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
}

.tree-search {
  margin-bottom: 16px;
}

.tree-container {
  height: calc(100vh - 300px);
  overflow-y: auto;
}

.tree-node {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
}

.tree-actions {
  margin-left: auto;
  visibility: hidden;
}

:deep(.el-tree-node__content:hover) .tree-actions {
  visibility: visible;
}

.query-form {
  margin-bottom: 16px;
}

.table-toolbar {
  margin-bottom: 16px;
}

.pagination {
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
}

.selection-hint {
  margin-left: 12px;
  font-size: 14px;
  color: var(--el-text-color-secondary);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}


:deep(.el-table) {
  --el-table-border-color: #eaeaea;
}

:deep(.el-tree) {
  --el-tree-node-hover-bg-color: #f5f7fa;
}
</style>